apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: d8allowedflexvolumes
  labels:
    heritage: deckhouse
    module: admission-policy-engine
    security.deckhouse.io: security-policy
  annotations:
    metadata.gatekeeper.sh/title: "List of allowed flex volume drivers"
    metadata.gatekeeper.sh/version: 1.0.0
    description: >-
      Controls the allowlist of FlexVolume drivers. Corresponds to the
      `allowedFlexVolumes` field in PodSecurityPolicy. For more information,
      see
      https://kubernetes.io/docs/concepts/policy/pod-security-policy/#flexvolume-drivers
spec:
  crd:
    spec:
      names:
        kind: D8AllowedFlexVolumes
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          type: object
          description: >-
            Controls the allowlist of FlexVolume drivers. Corresponds to the
            `allowedFlexVolumes` field in PodSecurityPolicy. For more information,see
            https://kubernetes.io/docs/concepts/policy/pod-security-policy/#flexvolume-drivers
          properties:
            allowedFlexVolumes:
              type: array
              description: "An array of AllowedFlexVolume objects."
              items:
                type: object
                properties:
                  driver:
                    description: "The name of the FlexVolume driver."
                    type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package d8.security_policies

        violation[{"msg": msg, "details": {}}] {
            volume := input_flexvolumes[_]
            not input_flexvolumes_allowed(volume)
            msg := sprintf("FlexVolume %v is not allowed, pod: %v. Allowed drivers: %v", [volume, input.review.object.metadata.name, input.parameters.allowedFlexVolumes])
        }

        input_flexvolumes_allowed(volume) {
            input.parameters.allowedFlexVolumes[_].driver == volume.flexVolume.driver
        }

        input_flexvolumes[v] {
            v := input.review.object.spec.volumes[_]
            has_field(v, "flexVolume")
        }

        # has_field returns whether an object has a field
        has_field(object, field) = true {
            object[field]
        }
